package com.yc.tomcat1;

import org.apache.log4j.Logger;

import java.io.File;
import java.io.InputStream;
import java.net.Socket;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 从输入流中读取http请求 解析出相应的信息
 * @author zwei
 * @create 2024-07-27 9:21
 */
public class YcHttpServletRequest {
    private Logger logger = Logger.getLogger(YcHttpServletRequest.class);
    private Socket s;
    private InputStream iis;
    //GET，post，put，delete，head，options，patch
    private String method;
    //定位符 请求地址          //http://localhost:8080....
    private String requestURL;
    //标识符 资源地址          doUpload.action
    private String requestURI;
    //上下文
    private String contextPath;
    //请求字符串  请求的地址栏参数
    private String queryString;
    //参数  地址栏参数  uname=123&pwd=123
    private Map<String,String[]>parameterMap=new ConcurrentHashMap<>();
    //协议类型  http：//
    private String schema;
    //协议版本  HTTP/1.1
    private String protocol;
    //项目的真实路径
    private String realPath;

    public YcHttpServletRequest(Socket s,InputStream iis) {
        this.s = s;
        this.iis = iis;
        this.parseRequest();
    }

    //解析方法
    private void parseRequest() {
        String requestInfoString=readFromInputStream(); //从输入流中读取http请求信息
        if (requestInfoString==null||"".equals(requestInfoString)){
            throw new RuntimeException("请求信息为空");
        }
        //解析http请求信息
        parseRequestInfoString(requestInfoString);
    }

    /**
     * 解析http请求头(存各种信息)
     * @param requestInfoString ： http请求协议
     *                              method 资源地址 协议版本
     *                              请求头域键 值
     *                              空行
     *                             资源地址 /yc/index.html?uname=123&pwd=123
     */
    private void parseRequestInfoString(String requestInfoString) {
        StringTokenizer st=new StringTokenizer(requestInfoString);  //按 空格切割
        this.method=st.nextToken();
        this.requestURI=st.nextToken();
        //requestURI要考虑地址栏参数
        int questionIndex=this.requestURI.indexOf("?");
        if (questionIndex>=0){
            //即有？有地址栏参数 --》参数存 queryString属性
            this.queryString=this.requestURI.substring(questionIndex+1);
            this.requestURI=this.requestURI.substring(0,questionIndex);
        }
        //第三部分：协议版本 http/1.1
        this.protocol=st.nextToken();
        //http
        this.schema=this.protocol.substring(0,this.protocol.indexOf("/"));
        //requestURL:/yc/index.html
        //www.baidu.com   ->get
        //contextPath  /yc
        //
        int salsh2Index=this.requestURI.indexOf("/",1);
        if (salsh2Index>=0){
            this.contextPath=this.requestURI.substring(0,salsh2Index);
        }else {
            this.contextPath=this.requestURI;
        }
        //requestURI:  URL统一资源定位符   http：//ip:端口/requestURL
        //this.requestURI=this.schema+"://"+this.s.getLocalSocketAddress()+this.requestURI;
        //参数处理 ：        /yc/index.html?uname=123&pwd=123
        //从 queryString中取出参数
        if(this.queryString!=null&&this.queryString.length()>0){
            String[]ps=this.queryString.split("&");
            for (String s:ps){
                String []param=s.split("=");
                //情况1  uname=123
                //情况2  ins=a,b,c
                this.parameterMap.put(param[0],param[1].split(","));
            }
            //TODO:     还有post的实体中也有可能有参数
        }
        this.realPath=System.getProperty("user.dir")+ File.separator+"webapp";


    }

    //从输入流中读取http请求信息(文本)
    private String readFromInputStream() {
        StringBuffer sb=null;
        int length=-1;
        byte []bs=new byte[300*1024];       //300k不考虑文件上传
        try {
            length=this.iis.read(bs,0,bs.length);
            //将byte[]转为字符串
            sb=new StringBuffer();
            for (int i=0;i<length;i++){
                sb.append((char) bs[i]);
            }
        } catch (Exception e){
            logger.error("读取请求数据失败");
        }
        return sb.toString();
    }

    public String[] getParameterValues(String name){
        if (parameterMap==null||parameterMap.size()<=0) {
            return null;
        }
        String []values=parameterMap.get(name);
        return values;
    }
    public String getParameter(String name){
        String[]values=getParameterValues(name);
        if (values==null||values.length<=0){
            return null;
        }
        return values[0];
    }

    public String getMethod() {
        return method;
    }

    public String getRequestURL() {
        return requestURL;
    }

    public String getRequestURI() {
        return requestURI;
    }

    public String getContextPath() {
        return contextPath;
    }

    public String getQueryString() {
        return queryString;
    }

    public Map<String, String[]> getParameterMap() {
        return parameterMap;
    }

    public String getSchema() {
        return schema;
    }

    public String getProtocol() {
        return protocol;
    }

    public String getRealPath() {
        return realPath;
    }
}
